package testt

import (
	"encoding/hex"
	"fmt"
	"log"

	"github.com/hyperledger/fabric-protos-go/common"
	"github.com/hyperledger/fabric-sdk-go/pkg/client/ledger"
	"github.com/hyperledger/fabric-sdk-go/pkg/core/config"
	"github.com/hyperledger/fabric-sdk-go/pkg/fabsdk"
	"github.com/pkg/errors"

	"github.com/golang/protobuf/proto"
)

const (
	//channelID   = "chl-01"
	channelID   = "chl-11"
	chaincodeID = "econtract"
	orgID       = "Org1"
	userID      = "Admin"
)

func t_main() {
	configOpt := config.FromFile("./config/sdk-config.yaml")
	sdk, err := fabsdk.New(configOpt)
	if err != nil {
		log.Fatalf("-X-> 创建新的SDK失败: %v\n", err)
		return
	}
	defer sdk.Close()
	log.Printf("---> 创建SDK成功\n")

	var options_user fabsdk.ContextOption
	var options_org fabsdk.ContextOption

	options_user = fabsdk.WithUser(userID)
	options_org = fabsdk.WithOrg(orgID)

	//cltContext := sdk.ChannelContext(channelID, options_user, options_org)

	clientChannelContext := sdk.ChannelContext(channelID, options_user, options_org)
	client, err := ledger.New(clientChannelContext)
	if err != nil {
		log.Fatalf("-X-> 创建sdk客户端失败: %v\n", err)
		return
	}

	info, err := client.QueryInfo()
	if err != nil {
		log.Fatalf("-X-> 查询区块链概况失败: %v\n", err)
		return
	}
	fmt.Printf("---> info:\n%#+v\n", info)

	fmt.Printf("区块高度:\n%v\n", info.BCI.Height)
	fmt.Printf("当前区块Hash:\n%v\n", hex.EncodeToString(info.BCI.CurrentBlockHash))
	fmt.Printf("前一区块Hash:\n%v\n", hex.EncodeToString(info.BCI.PreviousBlockHash))

	// 根据区块查询交易
	block, err := client.QueryBlock(info.BCI.Height - 1)
	//block, err := client.QueryBlock(44)
	if err != nil {
		log.Fatalf("-X-> 查询区块失败: %v\n", err)
		return
	}
	fmt.Printf("---> info:\n%#+v\n", block)
	// fmt.Printf("---> info:\n%#+v\n", block.Header)
	// fmt.Printf("---> info:\n%#+v\n", block.Metadata)
	// fmt.Printf("---> info:\n%#+v\n", block.Data)

	w1len := len(block.Data.Data)

	fmt.Printf("区块中交易笔数: %d\n", w1len)
	for i := 0; i < w1len; i++ {

	}
	// fmt.Printf("---> info:\n%#+v\n", block.Data.Data)

	envelope, err := GetEnvelopeFromBlock(block.Data.Data[0])
	if err != nil {
		panic(err)
	}
	// fmt.Println(string(envelope.Payload))

	payload := &common.Payload{}
	err = proto.Unmarshal(envelope.Payload, payload)
	if err != nil {
		panic(err)
	}

	// fmt.Println(payload)

	channelHeader := &common.ChannelHeader{}
	err = proto.Unmarshal(payload.Header.ChannelHeader, channelHeader)
	if err != nil {
		panic(err)
	}
	fmt.Printf("---> ChannelHeader\n%#v", channelHeader)
	// fmt.Println(channelHeader)

	// signatureHeader := &common.SignatureHeader{}
	// err = proto.Unmarshal(payload.Header.SignatureHeader, signatureHeader)
	// if err != nil {
	// 	panic(err)
	// }

	// fmt.Println(signatureHeader)

	// type SerializedIdentity struct {
	// 	Mspid   string
	// 	IdBytes []byte
	// }

	// creator := &msp.SerializedIdentity{}
	// err = proto.Unmarshal(signatureHeader.Creator, creator)
	// if err != nil {
	// 	panic(err)
	// }
	// fmt.Println(creator)

	// uEnc := base64.URLEncoding.EncodeToString([]byte(creator.IdBytes))

	// certText, err := base64.URLEncoding.DecodeString(uEnc)
	// if err != nil {
	// 	panic(err)
	// }

	// end, _ := pem.Decode([]byte(string(certText)))
	// if end == nil {
	// 	panic(err)
	// }
	// cert, err := x509.ParseCertificate(end.Bytes)
	// if err != nil {
	// 	panic(err)
	// }
	// fmt.Println(cert.Subject)

	// type Certificate struct {
	// 	Country            string
	// 	Organization       string
	// 	OrganizationalUnit string
	// 	Locality           string
	// 	Province           string
	// 	SerialNumber       string
	// 	NotBefore          string
	// 	NotAfter           string
	// }

	// certificateJson := Certificate{
	// 	Country:            cert.Issuer.Country,
	// 	Organization:       cert.Issuer.Organization,
	// 	OrganizationalUnit: cert.Issuer.OrganizationalUnit,
	// 	Locality:           cert.Issuer.Locality,
	// 	Province:           cert.Issuer.Province,
	// 	SerialNumber:       cert.Issuer.SerialNumber,
	// 	NotBefore:          cert.NotBefore,
	// 	NotAfter:           cert.NotAfter,
	// }

	// fmt.Println(certificateJson)

	//// -------------------- 第1种方式： 根据哈希查询区块 ----------------
	//block, err := client.QueryBlockByHash(info.BCI.CurrentBlockHash)
	//if err != nil {
	//log.Fatalf("查询区块信息失败: %v\n", err)
	//return
	//}
	//fmt.Printf("区块编号: %v\n", block.Header.Number)
	//fmt.Printf("区块Hash:\n%v\n", hex.EncodeToString(block.Header.DataHash))

	//// -------------------- 第1种方式： 根据块号查询区块 ----------------
	//blockNumber := info.BCI.Height - 1
	//block, err = client.QueryBlock(blockNumber)

	//fmt.Printf("区块编号: %v\n", block.Header.Number)
	//fmt.Printf("区块Hash:\n%v\n", hex.EncodeToString(block.Header.DataHash))

	//cfg, err := client.QueryConfig()

	//fmt.Println(cfg)
	//fmt.Printf("通道名称: %v\n", cfg.ID())
	//fmt.Printf("区块个数: %v\n", cfg.BlockNumber())
	//fmt.Printf("锚节点:\n  主机:%v\n  端口:%v\n  机构:%v\n", cfg.AnchorPeers()[0].Host, cfg.AnchorPeers()[0].Port, cfg.AnchorPeers()[0].Org)

}

func GetEnvelopeFromBlock(data []byte) (*common.Envelope, error) {
	var err error
	env := &common.Envelope{}
	if err = proto.Unmarshal(data, env); err != nil {
		return nil, errors.Wrap(err, "error unmarshaling Envelope")
	}

	return env, nil
}
